SciChart WPF 2D Charts > Tutorials > MVVM > Tutorial 05b - Adding Tooltips, Legends with MVVM
Tutorial 05b - Adding Tooltips, Legends with MVVM

Adding Tooltips and Legends in MVVM

Source code for this tutorial can be found at our SciChart.WPF.Examples Github Repository under Tutorials section.

Legends and Tooltips are pretty similar to the original Tutorial 05 - Adding Tooltips and Legends. We're going to add the LegendModifier and RolloverModifier to the View like this:

MainView.xaml - adding Legends and Tooltips
Copy Code
<!-- Inside your SciChartSurface.ChartModifier group -->
< s:SciChartSurface.ChartModifier>
    <s:ModifierGroup DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}" >
        <s:RubberBandXyZoomModifier IsEnabled="{Binding EnableZoom}" />
        <s:ZoomPanModifier IsEnabled="{Binding EnablePan}" ClipModeX="None" />
        <s:ZoomExtentsModifier/>
        <!-- NEW CODE HERE: Add the LegendModifier and RolloverModifier -->
        <s:LegendModifier ShowLegend="True" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Center"/>
        <s:RolloverModifier ShowTooltipOn="MouseHover"/>
        <!-- END NEW CODE -->
    </s:ModifierGroup>
</s:SciChartSurface.ChartModifier>

We won't add any bindings for now, but do note that you can control any property of the LegendModifier or RolloverModifier by binding to the MainViewModel (which is the current DataContext of the ChartModifiers). Or, the ChartViewModel if you prefer by changing the DataContext bindings in ModiiferGroup.

If you run the application now you will see the following:

Customizing the Tooltip Template with MVVM

Once youhave a tooltip setup, it is common to want to customize the tooltip template. To do this in MVVM, we use the technique described in the Worked Example - Bind Tooltip Templates or Attached Properties in MVVM article.

First, create a style in XAML to apply the tooltip template following the guidelines in the RolloverModifier Documentation.

Creating the Tooltip Template in XAML
Copy Code
<Window x:Class="SciChart.Mvvm.Tutorial.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SciChart.Mvvm.Tutorial"
        xmlns:s="http://schemas.abtsoftware.co.uk/scichart"
        mc:Ignorable="d"
        Title="MainWindow" Height="550" Width="800">
    <Window.Resources>
        <local:MainViewModel x:Key="MainViewModel"/>
        <!-- The TooltipControl template is defined below -->
        <!-- Change this if you want to have a non-default tooltip container -->
        <!-- The ContentPresenter is bound to the DataContext (a SeriesInfo type) -->
        <!-- and the ContentTemplate is the DataTemplate for the SeriesInfo -->
        <!-- Finally, the TooltipContainerStyle is set on the RenderableSeries via Style -->
        <Style x:Key="TooltipContainer" TargetType="s:TooltipControl">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="s:TooltipControl">
                        <Border Background="#ff6495ed"
                                BorderBrush="#ff87B1FA"
                                BorderThickness="2"
                                CornerRadius="53"
                                Opacity="0.9"
                                Padding="5">
                            <ContentPresenter Content="{TemplateBinding DataContext}"
                                              ContentTemplate="{TemplateBinding ContentTemplate}" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
       
        <!-- Tooltip Template for an XyDataSeries binds to XySeriesInfo -->
        <!-- Check out the properties on XySeriesInfo to see what you can bind to -->
        <DataTemplate x:Key="TooltipTemplate" DataType="s:XySeriesInfo">
            <StackPanel Orientation="Vertical">
                <TextBlock Foreground="White">
                    <Run Text="Series: "/>
                    <Run Text="{Binding SeriesName, StringFormat='{}{0}:'}"/>
                </TextBlock>
                <TextBlock Foreground="White">
                    <Run Text="X-Value: "/>
                    <Run Text="{Binding FormattedXValue, Mode=OneWay}"/>
                </TextBlock>
                <TextBlock Foreground="White">
                    <Run Text="Y-Value: "/>
                    <Run Text="{Binding FormattedYValue, Mode=OneWay}"/>
                </TextBlock>
            </StackPanel>
        </DataTemplate>
        <!-- Style applied via x:Key name in ViewModel. See StyleKey property of LineRenderableSeriesViewModel -->
        <Style TargetType="s:BaseRenderableSeries"  x:Key="LineSeriesStyle">
            <Setter Property="s:RolloverModifier.TooltipContainerStyle" Value="{StaticResource TooltipContainer}"/>
            <Setter Property="s:RolloverModifier.TooltipTemplate" Value="{StaticResource TooltipTemplate}"/>
            <Setter Property="s:RolloverModifier.IncludeSeries" Value="True"/>
            <Setter Property="StrokeThickness" Value="2"/>
        </Style>
    </Window.Resources>
    <Grid DataContext="{StaticResource MainViewModel}">
       
        <!-- New code here. Add RowDefinitions -->
        <Grid.RowDefinitions>
            <RowDefinition Height="32"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <!-- New code here: Add controls to toggle between zoom and pan -->
        <StackPanel Orientation="Horizontal" Background="#333">
            <CheckBox Margin="5" Foreground="#FFF" Content="Enable Zoom?" IsChecked="{Binding EnableZoom, Mode=TwoWay}"/>
            <CheckBox Margin="5" Foreground="#FFF" Content="Enable Pan?" IsChecked="{Binding EnablePan, Mode=TwoWay}" />
        </StackPanel>
       
        <!-- Don't forget to add Grid.Row=1 -->
        <s:SciChartSurface Grid.Row="1"
                           RenderableSeries="{s:SeriesBinding RenderableSeries}" 
                           ChartTitle="{Binding ChartTitle}">
                       
            <s:SciChartSurface.XAxis>
                <s:NumericAxis AxisTitle="{Binding XAxisTitle}"/>
            </s:SciChartSurface.XAxis>
            <s:SciChartSurface.YAxis>
                <s:NumericAxis AxisTitle="{Binding YAxisTitle}"/>
            </s:SciChartSurface.YAxis>
            <s:SciChartSurface.ChartModifier>
                <!-- Ensure ModifierGroup DataContext is the MainViewModel (not the ChartViewModel)-->
                <s:ModifierGroup>
                    <s:RubberBandXyZoomModifier IsEnabled="{Binding EnableZoom}" />
                    <s:ZoomPanModifier IsEnabled="{Binding EnablePan}" ClipModeX="None" />
                    <s:ZoomExtentsModifier/>
                    <!-- NEW CODE HERE: Add the LegendModifier and RolloverModifier -->
                    <s:LegendModifier ShowLegend="True" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Center"/>
                    <s:RolloverModifier ShowTooltipOn="MouseHover"/>
                    <!-- END NEW CODE -->
                </s:ModifierGroup>
            </s:SciChartSurface.ChartModifier>
           
        </s:SciChartSurface>
    </Grid>
</Window>

Now, apply the style with a single change to our ViewModel, applying the StyleKey on the LineRenderableSeriesViewModel:

MainViewModel changes
Copy Code
public MainViewModel()
{
    var lineData = new XyDataSeries<double, double>() { SeriesName = "TestingSeries" };
    lineData.Append(0, 0);
    lineData.Append(1, 1);
    lineData.Append(2, 2);
    _renderableSeries = new ObservableCollection<IRenderableSeriesViewModel>();
    RenderableSeries.Add(new LineRenderableSeriesViewModel()
    {
        StrokeThickness = 2,
        Stroke = Colors.SteelBlue,
        DataSeries = lineData,
        StyleKey = "LineSeriesStyle"
    });
}

This results in the following: